﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using Newtonsoft.Json;

namespace Lucilla.Framework.Web.Builders.SlickGrid
{
    /*
     * COLUMN DEFINITION (columns) OPTIONS:
     *     id                  - Column ID.
     *     name                - Column name to put in the header.
     *     toolTip             - Tooltip (if different from name).
     *     field               - Property of the data context to bind to.
     *     formatter           - (default 'return value || ""') Function responsible for rendering the contents of a cell. Signature: function formatter(row, cell, value, columnDef, dataContext) { ... return "..."; }
     *     editor              - An WithEditorFunction class.
     *     validator           - An extra validation function to be passed to the editor.
     *     unselectable        - If true, the cell cannot be selected (and therefore edited).
     *     cannotTriggerInsert - If true, a new row cannot be created from just the value of this cell.
     *     setValueHandler     - If true, this handler will be called to set field value instead of context[field].
     *     width               - Width of the column in pixels.
     *     resizable           - (default true) If false, the column cannot be resized.
     *     sortable            - (default false) If true, the column can be sorted (onSort will be called).
     *     minWidth            - Minimum allowed column width for resizing.
     *     maxWidth            - Maximum allowed column width for resizing.
     *     cssClass            - A CSS class to add to the cell.
     *     rerenderOnResize    - Rerender the column when it is resized (useful for columns relying on cell width or adaptive formatters).
     *     asyncPostRender     - Function responsible for manipulating the cell DOM node after it has been rendered (called in the background).
     *     behavior            - Configures the column with one of several available predefined behaviors:  "select", "move", "selectAndMove".
     */

    public delegate void ColumnConfigurator(Column column);

    [JsonObject(MemberSerialization.OptIn)]
    public class Column
    {
        public enum Behavior
        {
            selectAndMove,
            select,
            move
        }

        [JsonProperty]
        private string _id;
        [JsonProperty]
        private string _name;
        [JsonProperty]
        private string _tooltip;
        [JsonProperty]
        private string _field;
        [JsonProperty, JsonConverter(typeof(FunctionNameConverter))]
        private string _formatter;

        [JsonProperty, JsonConverter(typeof(FunctionNameConverter))]
        private string _editor;
        [JsonProperty, JsonConverter(typeof(FunctionNameConverter))]
        private string _validator;
        [DefaultValue(false), JsonProperty]
        private bool _unselectable;
        [JsonProperty, DefaultValue(false)]
        private bool _cannotTriggerInsert;
        [JsonProperty, JsonConverter(typeof(FunctionNameConverter))]
        private string _setValueHandler;
        [JsonProperty, DefaultValue((short)0)]
        private short _width;
        [JsonProperty, DefaultValue(true)]
        private bool _resizable;
        [JsonProperty, DefaultValue(false)]
        private bool _sortable;
        [JsonProperty, DefaultValue((short)0)]
        private short _minWidth;
        [JsonProperty, DefaultValue((short)0)]
        private short _maxWidth;
        [JsonProperty]
        private string _cssClass;
        [JsonProperty, DefaultValue(false)]
        private bool _rerenderOnResize;
        [JsonProperty, JsonConverter(typeof(FunctionNameConverter))]
        private string _asyncPostRender;
        [JsonProperty]
        private string _behavior;

        private SlickGridBuilder _slickGridBuilder;

        public Column(string id)
        {
            Id(id);
            Named(id);
            ForField(id);
            _resizable = true;
        }

        public SlickGridBuilder End()
        {
            return _slickGridBuilder;
        }

        public Column Id(string value)
        {
            _id = value;
            return this;
        }
        public Column Named(string value)
        {
            _name = value;
            return this;
        }

        public Column ForField(string value)
        {
            _field = value;
            return this;
        }

        public Column WithEditorFunction(string value)
        {
            _editor = value;
            return this;
        }

        public Column CssClass(string value)
        {
            _cssClass = value;
            return this;
        }

        public Column Tooltip(string value)
        {
            _tooltip = value;
            return this;
        }

        public Column Formatter(string value)
        {
            _formatter= value;
            return this;
        }

        public Column Validator(string value)
        {
            _validator = value;
            return this;
        }

        public Column Unselectable()
        {
            return Unselectable(true);
        }
        
        public Column Unselectable(bool value)
        {
            _unselectable = value;
            return this;
        }

        public Column CannotTriggerInsert()
        {
            return CannotTriggerInsert(true);
        }

        public Column CannotTriggerInsert(bool value)
        {
            _cannotTriggerInsert = value;
            return this;
        }

        public Column Width(short value)
        {
            _width = value;
            return this;
        }
        
        public Column Resizable()
        {
            return Resizable(true);
        }

        public Column Resizable(bool value)
        {
            _resizable = value;
            return this;
        }

        public Column Sortable()
        {
            return Sortable(true);
        }

        public Column Sortable(bool value)
        {
            _sortable = value;
            return this;
        }

        public Column MinWidth(short value)
        {
            _minWidth = value;
            return this;
        }

        public Column MaxWidth(short value)
        {
            _maxWidth = value;
            return this;
        }

        public Column WithSetValueHandler(string value)
        {
            _setValueHandler = value;
            return this;
        }
        
        public Column RerenderOnResize()
        {
            return RerenderOnResize(true);
        }

        public Column RerenderOnResize(bool value)
        {
            _rerenderOnResize = value;
            return this;
        }

        public Column AsyncPostRender(string value)
        {
            _asyncPostRender = value;
            return this;
        }

        public Column WithBehavior(Behavior value)
        {
            _behavior = value.ToString();
            return this;
        }

        public static Column ForId(string id)
        {
            return new Column(id);
        }

        public Column Configure(ColumnConfigurator configurator)
        {
            configurator(this);
            return this;
        }
    }
}
